﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Npgsql;
using System.Data;

namespace DataManagement
{
    class Conexion
    {
        internal NpgsqlConnection conexion;

        string Host;
        string Port;
        string User;
        string Pass;
        string DataBaseName;
        string formatoFecha;

        public Conexion(string Host, string Port, string User, string Pass, string DataBaseName)
        {
            this.Host = Host;
            this.Port = Port;
            this.User = User;
            this.Pass = Pass;
            this.DataBaseName = DataBaseName;
            conexion = new NpgsqlConnection(conexionString());
            setFormatoFecha();
        }

        private string conexionString()
        {
            return String.Format("Server={0};Port={1};User Id={2};Password={3};Database={4};",
                Host, Port, User, Pass, DataBaseName);
        }

        private void conexionPrueba()
        {
            conexion.Open();
            conexion.Close();
        }

        public String convertirFechaFormato(DateTime fecha)
        {
            String fechaFinal;
            //fechaFinal = fecha.Month.ToString() + "/" + fecha.Day.ToString() + "/" + fecha.Year.ToString();
            fechaFinal = fecha.Day.ToString() + "/" + fecha.Month.ToString() + "/" + fecha.Year.ToString();
            return fechaFinal;
        }

        public void insertarDependeciaUsuariosBase()
        {
            DataSet ds = new DataSet();
            DataSet dataSetActual = new DataSet();
            DataTable dt = new DataTable();
            DataSet dataSetAux = new DataSet();
            conexion.Open();
            string sql = "INSERT INTO Tipo_Perfil(nombre, permisosPredeterminados) VALUES ('Super Usuario', '11111111111111111111111111111111111111111111111111111')";
            NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conexion);
            ds.Reset();
            da.Fill(ds);
            sql = "INSERT INTO Tipo_Perfil(nombre, permisosPredeterminados) VALUES ('Usuario Estandar', '00000000000010110111000000000000100000001010011010000')";
            da = new NpgsqlDataAdapter(sql, conexion);
            ds.Reset();
            da.Fill(ds);
            sql = "INSERT INTO Tipo_Perfil(nombre, permisosPredeterminados) VALUES ('Usuario sin permisos', '00000000000000000000000000000000000000000000000000000')";
            da = new NpgsqlDataAdapter(sql, conexion);
            ds.Reset();
            da.Fill(ds);
            sql = "INSERT INTO Tipo_Usuario(nombre, descripcion, idTipoPerfil) VALUES ('Profesor', 'Permisos de docente.', 'TPerf - 2')";
            da = new NpgsqlDataAdapter(sql, conexion);
            ds.Reset();
            da.Fill(ds);
            sql = "INSERT INTO Tipo_Usuario(nombre, descripcion, idTipoPerfil) VALUES ('Unknown', 'Usuario sin permisos.', 'TPerf - 3')";
            da = new NpgsqlDataAdapter(sql, conexion);
            ds.Reset();
            da.Fill(ds);
            sql = "INSERT INTO Grupo(nombre, multaDiaria, descripcion, idTipoUsuario) VALUES ('Todos', 0, 'Grupo generado por defecto', 'TU - 1')";
            da = new NpgsqlDataAdapter(sql, conexion);
            ds.Reset();
            da.Fill(ds);
            sql = "INSERT INTO Grupo(nombre, multaDiaria, descripcion, idTipoUsuario) VALUES ('Unknown', 0, '', 'TU - 2')";
            da = new NpgsqlDataAdapter(sql, conexion);
            ds.Reset();
            da.Fill(ds);
            conexion.Close();
            sql = "INSERT INTO Tipo_Documento (nombre) VALUES ('Libro')";
            ejecutarSentencia(sql);
            sql = "INSERT INTO Atributo (idTipoDocumento, nombre, indizable, tipo) VALUES ('TipoDoc - 1', 'ISBN', false, 3)";
            ejecutarSentencia(sql);
            sql = "INSERT INTO Usuario VALUES ('unknown', 'Unknown', 'Unknown', 'Unknown', 'Unknown', false, 'Unknown', 'Unknown', 'Unknown', 'Unknown', 0, 'G - 2', '00000000000000000000000000000000000000000000000000000')";
            ejecutarSentencia(sql);
        }

        public void insertarUsuariosBase(LinkedList<Usuario> LU)
        {
            DataSet ds = new DataSet();
            DataSet dataSetActual = new DataSet();
            DataTable dt = new DataTable();
            DataSet dataSetAux = new DataSet();
            int i = 1;
            conexion.Open();
            foreach (Usuario u1 in LU)
            {
                string sql = "INSERT INTO USUARIO (idUsuario, Cedula, Nombre, Apellido1, Apellido2, Password, Domicilio, Email, Telefono, estado, idGrupo, permisos, sexo) VALUES ('" + i + "', '" + u1.cedula + "', '" + u1.nombre + "', '" + u1.apellido1 + "', '" + u1.apellido2 + "', 'biblioteca', '" + u1.domicilio + "', '" + u1.email + "', '" + u1.telefono + "', 0, 'G - 1', '00000000000010110111000000000000100000001010011010000', false)";
                NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conexion);
                ds.Reset();
                da.Fill(ds);
                i++;
            }
            conexion.Close();
        }

        public void ejecutarSentencia(String sentencia)
        {
            try
            {
                DataSet ds = new DataSet();
                DataSet dataSetActual = new DataSet();
                DataTable dt = new DataTable();
                DataSet dataSetAux = new DataSet();
                //conexion.Open();
                NpgsqlDataAdapter da = new NpgsqlDataAdapter(sentencia, conexion);
                dataSetActual.Reset();
                da.Fill(dataSetActual);
                //conexion.Close();
            }
            catch (Exception e)
            { }
        }

        public DataTable ejecutarSentenciaRetorno(String sentencia)
        {
            try
            {
                DataSet ds = new DataSet();
                DataSet dataSetActual = new DataSet();
                DataTable dt = new DataTable();
                DataSet dataSetAux = new DataSet();
                //conexion.Open();
                NpgsqlDataAdapter da = new NpgsqlDataAdapter(sentencia, conexion);
                dataSetActual.Reset();
                da.Fill(dataSetActual);
                dt = dataSetActual.Tables[0];
                //conexion.Close();
                return dt;
            }
            catch (Exception e)
            { return null; }
        }

        public void insertarMonosilabosBase(LinkedList<String> LM)
        {
            DataSet ds = new DataSet();
            DataSet dataSetActual = new DataSet();
            DataTable dt = new DataTable();
            DataSet dataSetAux = new DataSet();
            conexion.Open();
            foreach (String x in LM)
            {
                string sql = "INSERT INTO PALABRA_OMITIDA (Palabra) VALUES ('" + x + "')";
                NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conexion);
                ds.Reset();
                da.Fill(ds);
            }
            conexion.Close();
        }

        public void ingresarDatos(LinkedList<autor> LA, LinkedList<ejemplar> LE, LinkedList<documento> LD)
        {
            conexion.Open();
            DataSet dataset1 = new DataSet();
            DataTable dataAux = new DataTable();
            DataTable dataAux2 = new DataTable();
            DataTable dataActual = new DataTable();
            bool autorIgual=false;
            bool docEncontrado=false;
            string sql;
            int pk = 1;
            String idDocumento="";
            
            for (int i = 0; i < LD.Count; i++)
            {
                Console.WriteLine(i);
                sql = "SELECT * FROM DOCUMENTO WHERE Titulo = '" + LD.ElementAt(i).titulo + "'"; // FIJARSE SI EL DOC EXISTE
                dataActual.Reset();
                dataActual = ejecutarSentenciaRetorno(sql);
                if (dataActual.Rows.Count != 0)  // SI EXISTE
                {
                    docEncontrado = true;
                    sql = "SELECT d.idAutor FROM Documento AS d WHERE d.idDocumento = '" + dataActual.Rows[0].ItemArray.ElementAt(0).ToString() +"'";
                    dataAux.Reset();
                    dataAux = ejecutarSentenciaRetorno(sql);
                    if (dataAux.Rows.Count != 0)
                    {
                        String nombreAutor = dataAux.Rows[0].ItemArray.ElementAt(0).ToString();
                        if (nombreAutor != LA.ElementAt(i).nombre) autorIgual = false;
                        else autorIgual = true;
                    }
                    else autorIgual = false;
                }
                else // SI NO EXISTE
                {
                    docEncontrado = false;
                    autorIgual = false;
                }

                if ((docEncontrado == false) || (docEncontrado == true && autorIgual == false) ) // Si el documento se encontro y el autor era diferente
                {
                    

                    //if (!LA.ElementAt(i).nombre.Equals(""))
                    //{
                        sql = "SELECT * FROM AUTOR WHERE NOMBRE ='" + LA.ElementAt(i).nombre + "'";
                        dataAux2.Reset();
                        dataAux2 = ejecutarSentenciaRetorno(sql);
                        if (dataAux2.Rows.Count == 0)
                        {
                            //String idAutor = dataAux2.Rows[0].ItemArray.ElementAt(0).ToString();
                            sql = "INSERT INTO AUTOR (nombre) VALUES ('" + LA.ElementAt(i).nombre + "')";
                            ejecutarSentencia(sql);
                        }
                        /*else 
                        {
                            sql = "INSERT INTO AUTOR (nombre) VALUES ('" + LA.ElementAt(i).nombre + "')";
                            ejecutarSentencia(sql);
                            sql = "SELECT * FROM lastval();";
                            dataAux2.Reset();
                            dataAux2 = ejecutarSentenciaRetorno(sql);
                            String idAutor = "Autor - " + dataAux2.Rows[0].ItemArray.ElementAt(0).ToString();
                            sql = "INSERT INTO AUTOR_DOCUMENTO (idAutor, idDocumento) VALUES ('" + idAutor + "', '" + pk + "')";
                            ejecutarSentencia(sql);
                        }*/
                    //}
                        sql = "INSERT INTO DOCUMENTO (idDocumento, Titulo, Clasificacion, idAutor, Virtual, idTipoDocumento) VALUES ('" + pk + "', '" + LD.ElementAt(i).titulo + "', '" + LD.ElementAt(i).clasificacion + "', '" + LA.ElementAt(i).nombre + "', false, 'TipoDoc - 1')";
                        ejecutarSentencia(sql);
                        sql = "INSERT INTO VALORCAMPO VALUES ('" + LD.ElementAt(i).ISBN + "','Atr - 1', 'TipoDoc - 1')";
                        sql = "INSERT INTO EJEMPLAR (idEjemplar, fechaIngreso, idDocumento, estado) VALUES ('" + LE.ElementAt(i).numAdquisicion + "', '" + formatDate(LE.ElementAt(i).fechaIngreso) + "', '" + pk + "', 0)";
                        ejecutarSentencia(sql);
                        //sql = "SELECT Indizar ('" + pk +  "')";
                        //ejecutarSentencia(sql);

                    pk++;
                }
                //if (docEncontrado == true || autorIgual == true)
                else
                {                    
                    idDocumento = dataActual.Rows[0].ItemArray.ElementAt(0).ToString();
                    sql = "INSERT INTO EJEMPLAR (idEjemplar, fechaIngreso, idDocumento, estado) VALUES ('" + LE.ElementAt(i).numAdquisicion + "', '" + formatDate(LE.ElementAt(i).fechaIngreso) + "', '" + idDocumento + "', 0)";
                    ejecutarSentencia(sql);
                }
                
            }
            conexion.Close();
        }

        private void setFormatoFecha()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();
            try
            {
                conexion.Open();
                string sql = "SHOW DATESTYLE";
                NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conexion);
                ds.Reset();
                da.Fill(ds);
                dt = ds.Tables[0];
                string[] valores = null;
                foreach (DataRow row in dt.Rows)
                {
                    valores = datosDataSet(row, 1);
                    formatoFecha = (valores[0].Split(',')[1].ToUpper()).Trim();
                }
            }
            catch
            {
            }
            finally
            {
                try
                {
                    conexion.Close();
                }
                catch { }
            }
        }

        public string formatDate(DateTime fecha)
        {
            string[] a = new string[3];
            a[pos(formatoFecha, 'D')] = fecha.Day.ToString();
            a[pos(formatoFecha, 'M')] = fecha.Month.ToString();
            a[pos(formatoFecha, 'Y')] = fecha.Year.ToString();
            return a[0] + '-' + a[1] + '-' + a[2];
        }

        private static int pos(string cadena, char a)
        {
            int count = 0;
            foreach (char actual in cadena)
            {
                if (actual == a)
                {
                    return count;
                }
                count++;
            }
            return -1;
        }

        public DateTime formatDate(string fecha)
        {
            if (formatoFecha == "MDY")
            {
                string[] campos = fecha.Split('-', '/', ' ');
                int[] dias = new int[3];
                dias[2] = int.Parse(campos[pos(formatoFecha, 'Y')]);
                dias[0] = int.Parse(campos[pos(formatoFecha, 'M')]);
                dias[1] = int.Parse(campos[pos(formatoFecha, 'D')]);
                DateTime nuevo = new DateTime(dias[2], dias[1], dias[0]);
                return nuevo;
            }
            else
            {
                string[] campos = fecha.Split('-', '/', ' ');
                int[] dias = new int[3];
                dias[2] = int.Parse(campos[pos(formatoFecha, 'Y')]);
                dias[1] = int.Parse(campos[pos(formatoFecha, 'M')]);
                dias[0] = int.Parse(campos[pos(formatoFecha, 'D')]);
                DateTime nuevo = new DateTime(dias[2], dias[1], dias[0]);
                return nuevo;
            }
        }

        protected string[] datosDataSet(DataRow ds, int n)
        {
            string[] nuevo = new string[n];
            for (int i = 0; i < n; i++)
            {
                nuevo[i] = Convert.ToString(ds[i]);
            }
            return nuevo;
        }
    }
}
